﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Lesson13_异步_服务端综合练习
{
    class ServerSocket
    {
        private Socket socket;
        private Dictionary<int, ClientSocket> clientDic = new Dictionary<int, ClientSocket>();
        //待移除的客户端
        private List<ClientSocket> delList = new List<ClientSocket>();

        public void Start(string ip, int port, int num)
        {
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(ip), port);
            try
            {
                socket.Bind(ipPoint);
                socket.Listen(num);
                socket.BeginAccept(AcceptCallBack, null);
                Console.WriteLine("[ServerSocket][Start] success({0}:{1})!", ip, port);
            }
            catch (SocketException e)
            {
                Console.WriteLine("[ServerSocket][Start] error code:{0}", e.SocketErrorCode);
            }
        }

        private void AcceptCallBack(IAsyncResult result)
        {
            try
            {
                //通过调用EndAccept就可以得到连入的客户端Socket
                Socket clientSocket = this.socket.EndAccept(result);
                ClientSocket client = new ClientSocket(clientSocket);
                this.clientDic.Add(client.clientID, client);
                Console.WriteLine("[ServerSocket][AcceptCallBack] 客户端[{0}-{1}]连入.", client.clientID, clientSocket.RemoteEndPoint.ToString());
                //继续监听连接
                this.socket.BeginAccept(AcceptCallBack, this.socket);
            }
            catch (SocketException e)
            {
                Console.WriteLine("[ServerSocket][AcceptCallBack] error code:{0}", e.SocketErrorCode);
            }
        }

        public void Broadcast(BaseMsg msg)
        {
            Console.WriteLine("[ServerSocket][AcceptCallBack] Broadcast:{0}", msg);
            if (socket == null)
                return;
            foreach (ClientSocket client in clientDic.Values)
            {
                client.Send(msg);
            }
        }

        public void Close()
        {
            if (socket == null)
                return;
            lock (clientDic)
            {
                foreach (ClientSocket client in clientDic.Values)
                {
                    client.Close();
                }
            }
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
            socket = null;
            Console.WriteLine("[ServerSocket][Close] Success.");
        }

        public void CloseClientSocket(ClientSocket socket)
        {
            //加个锁,多线程操作安全
            lock (clientDic)
            {
                socket.Close();
                if (clientDic.ContainsKey(socket.clientID))
                {
                    clientDic.Remove(socket.clientID);
                }
            }
        }
    }
}
